﻿using System;
using System.Reflection;
using System.Reflection.Emit;
using MessagePack.Formatters;
using MessagePack.Internal;

namespace MessagePack.Resolvers
{
	// Token: 0x02000109 RID: 265
	public class DynamicEnumResolver : IFormatterResolver
	{
		// Token: 0x060003BF RID: 959 RVA: 0x0000DE39 File Offset: 0x0000C239
		private DynamicEnumResolver()
		{
		}

		// Token: 0x060003C1 RID: 961 RVA: 0x0000DE5C File Offset: 0x0000C25C
		public IMessagePackFormatter<T> GetFormatter<T>()
		{
			return DynamicEnumResolver.FormatterCache<T>.formatter;
		}

		// Token: 0x060003C2 RID: 962 RVA: 0x0000DE64 File Offset: 0x0000C264
		private static TypeInfo_wzh BuildType(Type enumType)
		{
			Type underlyingType = Enum.GetUnderlyingType(enumType);
			Type type = typeof(IMessagePackFormatter<>).MakeGenericType(new Type[]
			{
				enumType
			});
			TypeBuilder typeBuilder = DynamicEnumResolver.assembly.ModuleBuilder.DefineType("MessagePack.Formatters." + enumType.FullName.Replace(".", "_") + "Formatter", TypeAttributes.Public | TypeAttributes.Sealed, null, new Type[]
			{
				type
			});
			MethodBuilder methodBuilder = typeBuilder.DefineMethod("Serialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Final | MethodAttributes.Virtual, typeof(int), new Type[]
			{
				typeof(byte[]).MakeByRefType(),
				typeof(int),
				enumType,
				typeof(IFormatterResolver)
			});
			ILGenerator ilgenerator = methodBuilder.GetILGenerator();
			ilgenerator.Emit(OpCodes.Ldarg_1);
			ilgenerator.Emit(OpCodes.Ldarg_2);
			ilgenerator.Emit(OpCodes.Ldarg_3);
			ilgenerator.Emit(OpCodes.Call, typeof(MessagePackBinary).GetTypeInfo_wzh().GetDeclaredMethod("Write" + underlyingType.Name));
			ilgenerator.Emit(OpCodes.Ret);
			MethodBuilder methodBuilder2 = typeBuilder.DefineMethod("Deserialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Final | MethodAttributes.Virtual, enumType, new Type[]
			{
				typeof(byte[]),
				typeof(int),
				typeof(IFormatterResolver),
				typeof(int).MakeByRefType()
			});
			ILGenerator ilgenerator2 = methodBuilder2.GetILGenerator();
			ilgenerator2.Emit(OpCodes.Ldarg_1);
			ilgenerator2.Emit(OpCodes.Ldarg_2);
			ilgenerator2.Emit(OpCodes.Ldarg_S, 4);
			ilgenerator2.Emit(OpCodes.Call, typeof(MessagePackBinary).GetTypeInfo_wzh().GetDeclaredMethod("Read" + underlyingType.Name));
			ilgenerator2.Emit(OpCodes.Ret);
			//return typeBuilder.CreateTypeInfo();
			return null;
		}

		// Token: 0x0400015F RID: 351
		public static readonly DynamicEnumResolver Instance = new DynamicEnumResolver();

		// Token: 0x04000160 RID: 352
		private const string ModuleName = "MessagePack.Resolvers.DynamicEnumResolver";

		// Token: 0x04000161 RID: 353
		private static readonly DynamicAssembly assembly = new DynamicAssembly("MessagePack.Resolvers.DynamicEnumResolver");

		// Token: 0x0200010A RID: 266
		private static class FormatterCache<T>
		{
			// Token: 0x060003C3 RID: 963 RVA: 0x0000E04C File Offset: 0x0000C44C
			static FormatterCache()
			{
				TypeInfo_wzh typeInfo = typeof(T).GetTypeInfo_wzh();
				if (typeInfo.IsNullable())
				{
					typeInfo = typeInfo.GenericTypeArguments[0].GetTypeInfo_wzh();
					if (!typeInfo.IsEnum)
					{
						return;
					}
					object formatterDynamic = DynamicEnumResolver.Instance.GetFormatterDynamic(typeInfo.AsType());
					if (formatterDynamic == null)
					{
						return;
					}
					DynamicEnumResolver.FormatterCache<T>.formatter = (IMessagePackFormatter<T>)Activator.CreateInstance(typeof(StaticNullableFormatter<>).MakeGenericType(new Type[]
					{
						typeInfo.AsType()
					}), new object[]
					{
						formatterDynamic
					});
					return;
				}
				else
				{
					if (!typeInfo.IsEnum)
					{
						return;
					}
					TypeInfo_wzh typeInfo2 = DynamicEnumResolver.BuildType(typeof(T));
					DynamicEnumResolver.FormatterCache<T>.formatter = (IMessagePackFormatter<T>)Activator.CreateInstance(typeInfo2.AsType());
					return;
				}
			}

			// Token: 0x04000162 RID: 354
			public static readonly IMessagePackFormatter<T> formatter;
		}
	}
}
